package packed_widgets

import (
	"file_explorer/common/util"
	"file_explorer/model"
	"file_explorer/service/eventbus"

	"fyne.io/fyne/v2/theme"
)

type Checklist struct {
	*BaseComponent

	checkNum    int
	checkStatus []bool // 选中状态列表，用bind.Bool难以判断不同来源的变更

	moveUpButton     *Button
	moveDownButton   *Button
	moveTopButton    *Button
	moveBottomButton *Button
	reverseButton    *Button
	rangeButton      *Button
}

func (checklist *Checklist) publishStatusChange() {
	checklist.ProduceEvent(eventbus.EventKeyWidgetChecklistChange, map[string]interface{}{
		"checkNum": checklist.checkNum,
	})
}

func (checklist *Checklist) GetCheckNum() int {
	return checklist.checkNum
}
func (checklist *Checklist) GetCheckStatus(index int) bool {
	if index < 0 || index >= len(checklist.checkStatus) {
		return false
	}
	return checklist.checkStatus[index]
}

func (checklist *Checklist) GetCheckIndexList() []int {
	if checklist.checkNum == 0 {
		return nil
	}

	checkIndexList := make([]int, 0, checklist.checkNum)
	for i, checkStatus := range checklist.checkStatus {
		if !checkStatus {
			continue
		}
		checkIndexList = append(checkIndexList, i)
	}

	return checkIndexList
}

func (checklist *Checklist) SetCheckIndexList(checkIndexList []int) {
	for i := range checklist.checkStatus {
		checklist.checkStatus[i] = false
	}
	for _, index := range checkIndexList {
		checklist.checkStatus[index] = true
	}
	checklist.publishStatusChange()
}

func (checklist *Checklist) Check(index int, b bool) {
	if b == checklist.checkStatus[index] {
		return
	}
	checklist.checkStatus[index] = b
	if b {
		checklist.checkNum += 1
	} else {
		checklist.checkNum -= 1
	}
	checklist.publishStatusChange()
}

func (checklist *Checklist) CheckAll(b bool) {
	for index := range checklist.checkStatus {
		checklist.checkStatus[index] = b
	}
	checklist.checkNum = 0
	if b {
		checklist.checkNum = len(checklist.checkStatus)
	}
	checklist.publishStatusChange()
}

func (checklist *Checklist) CheckRange() {
	start, end := 0, 0
	for start = range checklist.checkStatus {
		if checklist.checkStatus[start] {
			break
		}
	}
	for end = len(checklist.checkStatus) - 1; end > start; end-- {
		if checklist.checkStatus[end] {
			break
		}
	}
	for i := start + 1; i < end; i++ {
		checklist.checkStatus[i] = true
	}
	checklist.checkNum = end - start + 1
	checklist.publishStatusChange()
}

func (checklist *Checklist) Toggle(index int) {
	checklist.checkStatus[index] = !checklist.checkStatus[index]
	if checklist.checkStatus[index] {
		checklist.checkNum += 1
	} else {
		checklist.checkNum -= 1
	}
	checklist.publishStatusChange()
}

func (checklist *Checklist) ToggleAll() {
	for index := range checklist.checkStatus {
		checklist.checkStatus[index] = !checklist.checkStatus[index]
	}
	checklist.checkNum = len(checklist.checkStatus) - checklist.checkNum
	checklist.publishStatusChange()
}

func (checklist *Checklist) Reset(size int) {
	checklist.checkStatus = make([]bool, size)
	checklist.checkNum = 0
	checklist.publishStatusChange()
}

func (checklist *Checklist) moveCheckList(allDataList []interface{}, updateData func(interfaces []interface{}), offset int) {
	checkIndexList := util.MoveListItems(allDataList, checklist.GetCheckIndexList(), offset)
	checklist.SetCheckIndexList(checkIndexList)
	updateData(allDataList)
}

func (checklist *Checklist) GetMoveUpButton(getData func() []interface{}, updateData func(interfaces []interface{})) *Button {
	if checklist.moveUpButton != nil {
		return checklist.moveUpButton
	}
	checklist.moveUpButton = NewButton("上移", theme.MoveUpIcon(), func() {
		checklist.moveCheckList(getData(), updateData, -1)
	})
	if checklist.GetCheckNum() < 1 {
		checklist.moveUpButton.Disable()
	}
	checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		if checklist.GetCheckNum() < 1 {
			checklist.moveUpButton.Disable()
			return
		}
		checklist.moveUpButton.Enable()
	})
	return checklist.moveUpButton
}

func (checklist *Checklist) GetMoveDownButton(getData func() []interface{}, updateData func(interfaces []interface{})) *Button {
	if checklist.moveDownButton != nil {
		return checklist.moveDownButton
	}
	checklist.moveDownButton = NewButton("下移", theme.MoveDownIcon(), func() {
		checklist.moveCheckList(getData(), updateData, 1)
	})
	if checklist.GetCheckNum() < 1 {
		checklist.moveDownButton.Disable()
	}
	checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		if checklist.GetCheckNum() < 1 {
			checklist.moveDownButton.Disable()
			return
		}
		checklist.moveDownButton.Enable()
	})
	return checklist.moveDownButton
}

func (checklist *Checklist) GetMoveTopButton(getData func() []interface{}, updateData func(interfaces []interface{})) *Button {
	if checklist.moveTopButton != nil {
		return checklist.moveTopButton
	}
	checklist.moveTopButton = NewButton("置顶", theme.UploadIcon(), func() {
		checklist.moveCheckList(getData(), updateData, -len(getData()))
	})
	if checklist.GetCheckNum() < 1 {
		checklist.moveTopButton.Disable()
	}
	checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		if checklist.GetCheckNum() < 1 {
			checklist.moveTopButton.Disable()
			return
		}
		checklist.moveTopButton.Enable()
	})
	return checklist.moveTopButton
}

func (checklist *Checklist) GetMoveBottomButton(getData func() []interface{}, updateData func(interfaces []interface{})) *Button {
	if checklist.moveBottomButton != nil {
		return checklist.moveBottomButton
	}
	checklist.moveBottomButton = NewButton("置底", theme.DownloadIcon(), func() {
		checklist.moveCheckList(getData(), updateData, len(getData()))
	})
	if checklist.GetCheckNum() < 1 {
		checklist.moveBottomButton.Disable()
	}
	checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		if checklist.GetCheckNum() < 1 {
			checklist.moveBottomButton.Disable()
			return
		}
		checklist.moveBottomButton.Enable()
	})
	return checklist.moveBottomButton
}

func (checklist *Checklist) GetReverseButton() *Button {
	if checklist.reverseButton != nil {
		return checklist.reverseButton
	}
	checklist.reverseButton = NewButton("反选", theme.SearchReplaceIcon(), func() {
		checklist.ToggleAll()
	})
	return checklist.reverseButton
}

func (checklist *Checklist) GetRangeButton() *Button {
	if checklist.rangeButton != nil {
		return checklist.rangeButton
	}
	checklist.rangeButton = NewButton("区间选择", theme.ListIcon(), func() {
		checklist.CheckRange()
	})
	if checklist.checkNum < 2 {
		checklist.rangeButton.Disable()
	}
	checklist.RegisterConsumer(eventbus.EventKeyWidgetChecklistChange, func(event *model.Event) {
		if checklist.GetCheckNum() < 2 {
			checklist.rangeButton.Disable()
			return
		}
		checklist.rangeButton.Enable()
	})
	return checklist.rangeButton
}

func NewChecklist() *Checklist {
	checklist := &Checklist{
		BaseComponent: NewBaseComponent(),
	}

	return checklist
}
